package com.yanqu.road.logic.model.kowloon.sanxiao;

import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.kowloon.enums.eKowloonBlockType;
import com.yanqu.road.entity.kowloon.enums.eKowloonShapeType;
import com.yanqu.road.entity.kowloon.sanxiao.*;
import com.yanqu.road.logic.model.kowloon.KowloonConfig;
import com.yanqu.road.utils.RandomHelper;

import java.util.*;

public class KowloonBlockComposeLogic {

    private static RandomHelper randomHelper = new RandomHelper();

    /**
     * 获取合成的方块
     */
    public static KowloonCreateBlockResult getCreateBlockList(int round, int fromX, int fromY, int toX, int toY,
                                                              Set<KowloonBlock> eliminateSet, Set<KowloonBlock> dropSet,
                                                              KowloonEliminateParam param) {
        KowloonCreateBlockResult createResult = new KowloonCreateBlockResult();

        List<KowloonBlock> addBlockList = new ArrayList<>();
        // 分组
        Map<Integer, List<List<KowloonBlock>>> listListMap = groupEliminateSet(eliminateSet);

        // 遍历生成新方块
        for (List<List<KowloonBlock>> listList : listListMap.values()) {
            for (int i = 0; i < listList.size(); i++) {
                List<KowloonBlock> list = listList.get(i);
                // 匹配形状
                KowloonShapeMatchResult matchResult = KowloonShapeLogic.matchShape(list);
                if (matchResult != null) {
                    if (matchResult.getShapeConfig().getShapeType().equals(eKowloonShapeType.ZhiXian5)) {
                        //直线5个高亮
                        for (KowloonBlock block : matchResult.getUseBlockList()) {
                            block.setHightlight(1);
                        }
                    }
                    // 生成新方块
                    List<KowloonBlock> newBlockList = createNewBlock(matchResult, round, fromX, fromY, toX, toY, dropSet, param);
                    addBlockList.addAll(newBlockList);
                    // 剩余格子继续生成炸弹
                    list.removeAll(matchResult.getUseBlockList());
                    if (!list.isEmpty()) {
                        i--;
                    }
                } else {
                    //按形状消完后,不能消的,放回去
                    addBlockList.addAll(list);
                }
            }
        }
        createResult.setBlockList(addBlockList);
        return createResult;
    }

    /**
     * 方块升级后的类型
     *
     * @param oldType
     * @return
     */
    public static int blockLvUpType(int oldType) {
        if (oldType == eKowloonBlockType.Silver.getValue()) {
            return eKowloonBlockType.Skill.getValue();
        }
        Map<Integer, Integer> heroElementMap = KowloonConfig.getHeroElementMap();
        for (Map.Entry<Integer, Integer> entry : heroElementMap.entrySet()) {
            if (oldType == entry.getValue()) {
                return entry.getKey();
            }
        }
        return oldType;
    }

    /**
     * 生成新方块
     */
    public static List<KowloonBlock> createNewBlock(KowloonShapeMatchResult result,
                                                    int round, int fromX, int fromY, int toX, int toY,
                                                    Set<KowloonBlock> dropSet, KowloonEliminateParam param) {
        // 【找生成方块的位置】
        KowloonCalcLvUpBlockPosResult newBlockPosResult = calcCreateBlockPos(result, round, fromX, fromY, toX, toY, dropSet);

        //N3消时最中间的好汉多升N4级
        int skill180AddLevel = handleSkill180LevelAdd(param, result);

        List<KowloonBlock> blockList = new ArrayList<>();
        for (int i = 0; i < newBlockPosResult.getPosBlockList().size(); i++) {
            KowloonBlock newBlock = newBlockPosResult.getPosBlockList().get(i).clone();
            newBlock.setType(blockLvUpType(newBlock.getType()));
            newBlock.setHightlight(0);
            if (skill180AddLevel > 0 && i == newBlockPosResult.getPosBlockList().size() / 2 && newBlock.getType() != eKowloonBlockType.Skill.getValue()) {
                KowloonChooseHeroData chooseHero = param.getGameData().getChooseHero(newBlock.getType());
                int maxMergeLevel = param.getConfig().getMaxMergeLevel(chooseHero.getHeroId(), chooseHero.getLevel());
                newBlock.setLevel(Math.min(maxMergeLevel, newBlock.getLevel() + skill180AddLevel));
            }
            blockList.add(newBlock);
        }
        return blockList;
    }

    /**
     * 计算新方块生成位置
     */
    private static KowloonCalcLvUpBlockPosResult calcCreateBlockPos(KowloonShapeMatchResult result,
                                                                    int round, int fromX, int fromY, int toX, int toY,
                                                                    Set<KowloonBlock> dropSet) {
        List<KowloonBlock> useBlock = result.getUseBlockList();
        int createNum = result.getShapeConfig().getShapeType().getNewBlockNum();
        int createLevel = useBlock.get(0).getLevel() + 1;
        if (useBlock.get(0).getType() == eKowloonBlockType.Silver.getValue()) {
            createNum = result.getShapeConfig().getShapeType().getNewSkillNum();
            createLevel = result.getShapeConfig().getShapeType().getNewSkillLevel();
        }

        List<KowloonBlock> posLockList = new ArrayList<>();
        // 第一轮 && 包含交换的格子
        boolean firstRound = round == 1;
        if (createNum == 1) { //生成一个的要指定位置
            if (firstRound) {
                Optional<KowloonBlock> any = useBlock.stream().filter(item -> item.getX() == toX && item.getY() == toY).findAny();
                if (any.isPresent()) {
                    posLockList.add(any.get().setLevelAndRetrun(createLevel));
                    return new KowloonCalcLvUpBlockPosResult(posLockList, true);
                }
                any = useBlock.stream().filter(item -> item.getX() == fromX && item.getY() == fromY).findAny();
                if (any.isPresent()) {
                    posLockList.add(any.get().setLevelAndRetrun(createLevel));
                    return new KowloonCalcLvUpBlockPosResult(posLockList, true);
                }
            }

            // 包含掉落格子（useBlock是小到大排序的）
            for (KowloonBlock block : useBlock) {
                if (dropSet.contains(block)) { //掉落的格子合成后新格子的位置在中间
                    posLockList.add(useBlock.get(1).setLevelAndRetrun(createLevel));
                    return new KowloonCalcLvUpBlockPosResult(posLockList, false);
                }
            }
        } else { //生成大于1个的放中间
            eKowloonShapeType shapeType = result.getShapeConfig().getShapeType();
            if (shapeType == eKowloonShapeType.ZhiXianL || shapeType == eKowloonShapeType.ZhiXianT || shapeType == eKowloonShapeType.ZhiXianShiZi) {
                //先找到中间的坐标
                Map<Integer, Integer> xNumMap = new HashMap<>();
                Map<Integer, Integer> yNumMap = new HashMap<>();
                int middleX = -1;
                int middleY = -1;
                for (KowloonBlock block : useBlock) {
                    Integer xNum = xNumMap.getOrDefault(block.getX(), 0);
                    xNumMap.put(block.getX(), xNum + 1);
                    if (xNum > 0) {
                        middleX = block.getX();
                    }

                    Integer yNum = yNumMap.getOrDefault(block.getY(), 0);
                    yNumMap.put(block.getY(), yNum + 1);
                    if (yNum > 0) {
                        middleY = block.getY();
                    }

                    if (middleX != -1 && middleY != -1) {
                        break;
                    }
                }

                //取中间坐标和中间坐标旁边Y方向的
                for (KowloonBlock block : useBlock) {
                    if (block.getX() == middleX && block.getY() == middleY) {
                        posLockList.add(block.setLevelAndRetrun(createLevel));
                    }

                    if (block.getX() == middleX && Math.abs(block.getY() - middleY) == 1) {
                        posLockList.add(block.setLevelAndRetrun(createLevel));
                    }

                    if (posLockList.size() >= createNum) {
                        break;
                    }
                }
            } else {
                for (int i = createNum; i > 0; i--) {
                    posLockList.add(useBlock.get(i).setLevelAndRetrun(createLevel));
                }
            }

            return new KowloonCalcLvUpBlockPosResult(posLockList, false);
        }
        posLockList.add(useBlock.get(1).setLevelAndRetrun(createLevel));
        return new KowloonCalcLvUpBlockPosResult(posLockList, false);
    }

    /**
     * 消除的方块按颜色、相邻分组
     */
    public static Map<Integer, List<List<KowloonBlock>>> groupEliminateSet(Set<KowloonBlock> eliminateSet) {
        Map<Integer, List<List<KowloonBlock>>> listListMap = new HashMap<>();

        for (KowloonBlock block : eliminateSet) {
            listListMap.putIfAbsent(block.getEliminateType(), new ArrayList<>());
            List<List<KowloonBlock>> listList = listListMap.get(block.getEliminateType());

            // 和该方块相邻的方块位于list的哪些下标
            List<Integer> adjoinIndexList = new ArrayList<>();
            for (int i = 0; i < listList.size(); i++) {
                List<KowloonBlock> list = listList.get(i);
                for (KowloonBlock tmpBlock : list) {
                    if (tmpBlock.getEliminateType() == block.getEliminateType() && isBlockAdjoin(tmpBlock, block)) {
                        adjoinIndexList.add(i);
                        break;
                    }
                }
            }

            // 相邻的合并起来
            List<KowloonBlock> list = new ArrayList<>();
            list.add(block);
            for (Integer index : adjoinIndexList) {
                list.addAll(listList.get(index));
            }
            for (int i = adjoinIndexList.size() - 1; i >= 0; i--) {
                listList.remove((int) adjoinIndexList.get(i));
            }
            listList.add(list);
        }

        // 排个序吧，按位置小到大
        for (List<List<KowloonBlock>> listList : listListMap.values()) {
            for (List<KowloonBlock> list : listList) {
                list.sort(new Comparator<KowloonBlock>() {
                    @Override
                    public int compare(KowloonBlock o1, KowloonBlock o2) {
                        if (o1.getY() != o2.getY()) {
                            return o1.getY() - o2.getY();
                        } else if (o1.getX() != o2.getX()) {
                            return o1.getX() - o2.getX();
                        } else {
                            return 0;
                        }
                    }
                });
            }
        }

        return listListMap;
    }

    /**
     * 方块是否相邻（可斜消时斜着的也算相邻）
     */
    private static boolean isBlockAdjoin(KowloonBlock block1, KowloonBlock block2) {
        int subY = Math.abs(block1.getY() - block2.getY());
        int subX = Math.abs(block1.getX() - block2.getX());

        // 超过1必定不相邻
        if (subX > 1 || subY > 1) {
            return false;
        }

        int sum = subX + subY;
        int limit = 1;
        return sum <= limit;
    }

    /**
     * N3消时最中间的好汉多升N4级
     */
    private static int handleSkill180LevelAdd(KowloonEliminateParam param, KowloonShapeMatchResult result) {
        if (result.getShapeConfig().getShapeType() != eKowloonShapeType.ZhiXian5) {
            //只有直线5消才有,后面有新需求再改
            return 0;
        }
        KowloonGameData gameData = param.getGameData();
        SkillInfo skill180Info = null;
        for (KowloonSkill kowloonSkill : gameData.getSkillList()) {
            SkillInfo skillInfo = param.getKowloonSkillInfo(kowloonSkill.getSkillId());
            if (null == skillInfo) {
                continue;
            }
            if (skillInfo.getType() == eSkillType.KowloonSkill180.getValue()) {
                skill180Info = skillInfo;
                break;
            }
        }

        if (null == skill180Info) {
            return 0;
        }

        return skill180Info.getParamList().get(3);
    }
}
